feat: PrivateLink support (phase 1)#803
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements Phase 1 of PrivateLink support for the ScyllaDB Java Driver, introducing a configuration API for Client Routes to support AWS PrivateLink-style deployments. The implementation provides programmatic configuration for connection endpoints without the full handler implementation (deferred to future phases).
Changes:
- Introduced new API classes
ClientRoutesConfigandClientRoutesEndpointfor programmatic endpoint configuration - Extended
SessionBuilderwithwithClientRoutesConfig()method, including validation for mutual exclusivity with custom AddressTranslator and automatic seed host derivation - Added configuration option
advanced.client-routes.table-namewith supporting infrastructure inDefaultDriverOption,TypedDriverOption, andOptionsMap - Implemented URI-based address parsing supporting IPv4, IPv6 (bracketed), and hostname formats with port validation
- Extended
ProgrammaticArgumentsto pass client routes configuration through session initialization - Added comprehensive unit tests covering configuration builder, validation, and address parsing scenarios
- Updated documentation in
manual/core/address_resolution/README.mdexplaining client routes usage and constraints
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Updates native-protocol dependency to SNAPSHOT version for CLIENT_ROUTES support |
| core/src/main/java/com/datastax/oss/driver/api/core/config/ClientRoutesEndpoint.java | New immutable API class representing a single endpoint with connection ID and optional DNS address |
| core/src/main/java/com/datastax/oss/driver/api/core/config/ClientRoutesConfig.java | New immutable configuration container with builder pattern for managing client routes endpoints |
| core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java | Adds CLIENT_ROUTES_TABLE_NAME option for system table configuration |
| core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java | Adds typed wrapper for CLIENT_ROUTES_TABLE_NAME option |
| core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java | Sets default value "system.client_routes" for client routes table name |
| core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java | Integrates client routes configuration with validation, mutual exclusivity checks, and automatic seed host derivation using URI-based address parsing |
| core/src/main/java/com/datastax/oss/driver/api/core/session/ProgrammaticArguments.java | Extends to pass ClientRoutesConfig through session initialization |
| core/src/main/resources/reference.conf | Documents client-routes configuration section with table-name option |
| core/src/test/java/com/datastax/oss/driver/api/core/config/ClientRoutesConfigTest.java | Unit tests for ClientRoutesConfig builder functionality |
| core/src/test/java/com/datastax/oss/driver/api/core/session/ClientRoutesSessionBuilderTest.java | Tests for SessionBuilder integration with client routes |
| core/src/test/java/com/datastax/oss/driver/internal/core/session/ClientRoutesValidationTest.java | Comprehensive validation tests for address parsing edge cases |
| manual/core/address_resolution/README.md | Documentation for client routes feature with usage examples and constraints |
core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java
Show resolved
Hide resolved
.../src/test/java/com/datastax/oss/driver/internal/core/session/ClientRoutesValidationTest.java
Outdated
Show resolved
Hide resolved
core/src/test/java/com/datastax/oss/driver/api/core/session/ClientRoutesSessionBuilderTest.java
Outdated
Show resolved
Hide resolved
core/src/main/java/com/datastax/oss/driver/api/core/session/SessionBuilder.java
Outdated
Show resolved
Hide resolved
d61145d to
17991f3
Compare
… deployments Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
17991f3 to
a5140da
Compare
|
|
||
| import com.datastax.oss.driver.api.core.CqlIdentifier; | ||
| import com.datastax.oss.driver.api.core.CqlSession; | ||
| import com.datastax.oss.driver.api.core.addresstranslation.AddressTranslator; |
There was a problem hiding this comment.
AddressTranslator is imported but only referenced in Javadoc; Java treats that as unused, which can trigger unused-import checks and adds noise. Remove the import or reference the type in code (e.g., via a signature/field) if it’s intentionally needed.
| import com.datastax.oss.driver.api.core.addresstranslation.AddressTranslator; |
| } catch (Exception e) { | ||
| throw new IllegalArgumentException( | ||
| String.format( | ||
| "Failed to parse client routes endpoint address '%s' (connection ID: %s): %s", | ||
| addr, endpoint.getConnectionId(), e.getMessage()), | ||
| e); |
There was a problem hiding this comment.
The catch block wraps any exception from AddressParser and embeds e.getMessage() into a new message; since AddressParser already formats a full contextual message (including connectionId), this produces duplicated/verbose errors. Prefer letting IllegalArgumentException propagate as-is, or wrap without repeating the nested message; also narrow the catch to the expected exception type instead of Exception.
| } catch (Exception e) { | |
| throw new IllegalArgumentException( | |
| String.format( | |
| "Failed to parse client routes endpoint address '%s' (connection ID: %s): %s", | |
| addr, endpoint.getConnectionId(), e.getMessage()), | |
| e); | |
| } catch (IllegalArgumentException e) { | |
| throw e; |
| String.format("Invalid port %d. Port must be between 1 and 65535.", port))); | ||
| } | ||
|
|
||
| return new InetSocketAddress(host, port); |
There was a problem hiding this comment.
parseContactPoint returns new InetSocketAddress(host, port), which may trigger DNS resolution during parsing and only captures a single resolved address. To avoid blocking I/O during builder/config parsing and to let callers control resolution (and potentially expand multiple A-records), consider returning an unresolved address (InetSocketAddress.createUnresolved) or exposing host/port separately.
| return new InetSocketAddress(host, port); | |
| return InetSocketAddress.createUnresolved(host, port); |
| this.endpoints.clear(); | ||
| this.endpoints.addAll(endpoints); |
There was a problem hiding this comment.
withEndpoints(List<...>) clears and addAlls without validating that the list is non-empty and contains no null elements, even though the Javadoc states “must not be null or empty”. A null element can later cause NPEs (e.g., when iterating endpoints in SessionBuilder). Validate emptiness and reject null elements (or defensively copy with per-element null checks).
| this.endpoints.clear(); | |
| this.endpoints.addAll(endpoints); | |
| if (endpoints.isEmpty()) { | |
| throw new IllegalArgumentException("endpoints must not be empty"); | |
| } | |
| this.endpoints.clear(); | |
| for (ClientRoutesEndpoint endpoint : endpoints) { | |
| addEndpoint(endpoint); | |
| } |
Client Routes Configuration API (Phase 1)
Note: Depends on #java-native-protocol/45
Overview
Implements the configuration API for Client Routes feature to support PrivateLink-style cloud deployments (ScyllaDB Cloud). This is Phase 1 of the implementation - provides programmatic configuration without the full handler implementation.
Jira: DRIVER-88
Changes
New API Classes
ClientRoutesEndpoint- Represents a single endpoint with connection ID and optional DNS addressClientRoutesConfig- Immutable configuration container with builder patternSessionBuilder Integration
withClientRoutesConfig(ClientRoutesConfig)methodAddressTranslatorConfiguration
advanced.client-routes.table-nameoption (default:system.client_routes)ProgrammaticArgumentsto pass configuration through session initializationreference.confwith inline documentationAddress Parsing
Supported Address Formats
Usage Example
Testing
ClientRoutesConfigTest(8 tests)ClientRoutesSessionBuilderTest(2 tests, refactored to use Mockito)ClientRoutesValidationTestTypedDriverOptionTestandMapBasedDriverConfigLoaderTestDocumentation
manual/core/address_resolution/README.mdwith Client Routes sectionreference.confwith configuration optionschangelog/README.mdfor version 4.19.0Validation
✅ All unit tests passing (18 tests total)
✅ No compilation errors
✅ Mutual exclusivity validation working
✅ Seed host derivation working
✅ IPv6 support working
✅ Error messages clear and helpful
What's NOT Included (Future Work)
This PR provides the configuration API only. The following are intentionally deferred to future PRs:
CLIENT_ROUTES_CHANGEevent handling (stub exists inControlConnection)Design Decisions
Breaking Changes
None - this is a purely additive change.
Migration Guide
N/A - New feature, no migration needed.
Review Checklist
Related